package com.sicpa.web.controller.system;

import com.sicpa.common.annotation.Log;
import com.sicpa.common.constant.Constants;
import com.sicpa.common.constant.UserConstants;
import com.sicpa.common.core.controller.BaseController;
import com.sicpa.common.core.domain.AjaxResult;
import com.sicpa.common.core.domain.entity.AntiCounterfeitingCaBlacklist;
import com.sicpa.common.core.domain.entity.AntiCounterfeitingRegisteredOffice;
import com.sicpa.common.core.domain.entity.SysRole;
import com.sicpa.common.core.domain.entity.SysUser;
import com.sicpa.common.core.domain.model.LoginUser;
import com.sicpa.common.core.page.TableDataInfo;
import com.sicpa.common.core.redis.RedisCache;
import com.sicpa.common.enums.BusinessType;
import com.sicpa.common.utils.RandomNumCode;
import com.sicpa.common.utils.SecurityUtils;
import com.sicpa.common.utils.ServletUtils;
import com.sicpa.common.utils.StringUtils;
import com.sicpa.common.utils.poi.ExcelUtil;
import com.sicpa.common.utils.uuid.IdUtils;
import com.sicpa.framework.web.service.TokenService;
import com.sicpa.system.service.ISendMobileMessageService;
import com.sicpa.system.service.ISysRoleService;
import com.sicpa.system.service.ISysUserService;
import com.sicpa.vo.ForgetPwd;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.validation.constraints.NotBlank;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 用户信息
 *
 * @author ruoyi
 */
@Api(tags = "用户信息")
@RestController
@RequestMapping("/system/user")
public class SysUserController extends BaseController {
    private ISysUserService userService;

    private ISysRoleService roleService;

    private TokenService tokenService;
    private RedisCache redisCache;
    private ISendMobileMessageService iSendMobileMessageService;


    @Autowired
    public SysUserController(ISysUserService userService, ISysRoleService roleService, TokenService tokenService,RedisCache redisCache, ISendMobileMessageService iSendMobileMessageService) {
        this.userService = userService;
        this.roleService = roleService;
        this.tokenService = tokenService;
        this.redisCache = redisCache;
        this.iSendMobileMessageService = iSendMobileMessageService;
    }

    /**
     * 获取用户列表
     */
    @PreAuthorize("@ss.hasPermi('system:user:list')")
    @GetMapping("/list")
    public TableDataInfo list(SysUser user) {
        startPage();
        List<SysUser> list = userService.selectUserList(user);
        return getDataTable(list);
    }

    /**
     * 获取事务所用户列表
     */
    @PreAuthorize("@ss.hasPermi('system:officeUser:list')")
    @GetMapping("/officeUserList")
    public TableDataInfo selectOfficeUserList(SysUser user) {
        startPage();
        List<SysUser> list = userService.selectOfficeUserList(user);
        return getDataTable(list);
    }

    @Log(title = "用户管理", businessType = BusinessType.EXPORT)
    @PreAuthorize("@ss.hasPermi('system:user:export')")
    @GetMapping("/export")
    public AjaxResult export(SysUser user) {
        List<SysUser> list = userService.selectUserList(user);
        ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class);
        return util.exportExcel(list, "用户数据");
    }

    @Log(title = "用户管理", businessType = BusinessType.IMPORT)
    @PreAuthorize("@ss.hasPermi('system:user:import')")
    @PostMapping("/importData")
    public AjaxResult importData(MultipartFile file, boolean updateSupport) throws Exception {
        ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class);
        List<SysUser> userList = util.importExcel(file.getInputStream());
        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
        String operName = loginUser.getUsername();
        String message = userService.importUser(userList, updateSupport, operName);
        return AjaxResult.success(message);
    }

    @GetMapping("/importTemplate")
    public AjaxResult importTemplate() {
        ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class);
        return util.importTemplateExcel("用户数据");
    }

    /**
     * 根据用户编号获取详细信息
     */
    //  @PreAuthorize("@ss.hasPermi('system:user:query')")
    @GetMapping(value = {"/", "/{userId}"})
    public AjaxResult getInfo(@PathVariable(value = "userId", required = false) Long userId) {
        AjaxResult ajax = AjaxResult.success();
        List<SysRole> roles = roleService.selectRoleAll();
        ajax.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
        if (StringUtils.isNotNull(userId)) {
            ajax.put(AjaxResult.DATA_TAG, userService.selectUserById(userId));
            ajax.put("roleIds", roleService.selectRoleListByUserId(userId));
        }
        return ajax;
    }


    /**
     * 新增修改用户手机号--发送短信验证码
     *
     * @param phonenumber
     * @return
     */
    @ApiOperation(" 新增修改用户手机号--发送短信验证码")
    @GetMapping(value = "/sendTelCode")
    public AjaxResult sendMobileMessage( @NotBlank(message = "phonenumber不能为空") @RequestParam("phonenumber") String phonenumber) throws UnsupportedEncodingException {
        String mobileCode = RandomNumCode.generateNumCode();
        iSendMobileMessageService.sendMobileMessageGet(" 您的手机验证码是" + mobileCode + ",请在3分钟内按页面提示提交验证码!", phonenumber);
        String vuuid = IdUtils.simpleUUID();
        redisCache.setCacheObject(Constants.CAPTCHA_CODE_KEY + vuuid, mobileCode, Constants.MOBILE_EXPIRATION, TimeUnit.MINUTES);
        return AjaxResult.success(vuuid);
    }

    /**
     * 新增用户
     */
    @PreAuthorize("@ss.hasPermi('system:user:add')")
    @Log(title = "新增用户", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@Validated @RequestBody SysUser user) {
        if (UserConstants.NOT_UNIQUE.equals(userService.checkUserNameUnique(user.getUserName()))) {
            return AjaxResult.error("新增用户'" + user.getUserName() + "'失败，登录账号已存在");
        } else if (UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(user))) {
            return AjaxResult.error("新增用户'" + user.getUserName() + "'失败，手机号码已存在");
        } else if (user.getUuid()== null || user.getVerifyCode() == null) {
            return AjaxResult.error("新增用户'" + user.getUserName() + "'失败，手机号码验证码为空");
        }
        String verifyKey = Constants.CAPTCHA_CODE_KEY + user.getUuid();
        String mobileCode = redisCache.getCacheObject(verifyKey);
        if(!mobileCode.equalsIgnoreCase(user.getVerifyCode())){
            return AjaxResult.error("验证码错误!");
        }
        user.setCreateBy(SecurityUtils.getUsername());
        user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
        return toAjax(userService.insertUser(user));
    }

    /**
     * 修改用户
     */
    @PreAuthorize("@ss.hasPermi('system:user:edit')")
    @Log(title = "修改用户", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@Validated @RequestBody SysUser user) {
        userService.checkUserAllowed(user);
        if (UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(user))) {
            return AjaxResult.error("修改用户'" + user.getUserName() + "'失败，手机号码已存在");
        }
        if(user.getIsUpdateTel() != null  && user.getIsUpdateTel()== 1){
            if (user.getUuid()== null || user.getVerifyCode() == null) {
                return AjaxResult.error("修改用户'" + user.getUserName() + "'失败，手机号码验证码为空");
            }
            String verifyKey = Constants.CAPTCHA_CODE_KEY + user.getUuid();
            String mobileCode = redisCache.getCacheObject(verifyKey);
            if(!mobileCode.equalsIgnoreCase(user.getVerifyCode())){
                return AjaxResult.error("验证码错误!");
            }
        }

        user.setUpdateBy(SecurityUtils.getUsername());
        return toAjax(userService.updateUser(user));
    }

    /**
     * 删除用户
     */
    @PreAuthorize("@ss.hasPermi('system:user:remove')")
    @Log(title = "删除用户", businessType = BusinessType.DELETE)
    @DeleteMapping("/{userIds}")
    public AjaxResult remove(@PathVariable Long[] userIds) {
        return toAjax(userService.deleteUserByIds(userIds));
    }

    /**
     * 重置密码
     */
    @PreAuthorize("@ss.hasPermi('system:user:edit')")
    @Log(title = "重置密码", businessType = BusinessType.UPDATE)
    @PutMapping("/resetPwd")
    public AjaxResult resetPwd(@RequestBody SysUser user) {
        userService.checkUserAllowed(user);
        user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
        user.setUpdateBy(SecurityUtils.getUsername());
        return toAjax(userService.resetPwd(user));
    }

    /**
     * 状态修改
     */
    @PreAuthorize("@ss.hasPermi('system:user:edit')")
    @Log(title = "用户管理-状态修改", businessType = BusinessType.UPDATE)
    @PutMapping("/changeStatus")
    public AjaxResult changeStatus(@RequestBody SysUser user) {
        userService.checkUserAllowed(user);
        user.setUpdateBy(SecurityUtils.getUsername());
        return toAjax(userService.updateUserStatus(user));
    }

    /**
     * 查询用户管理的事务所列表
     *
     * @return 结果
     * @author wph 20200914
     */
    @PreAuthorize("@ss.hasPermi('system:user:allocation')")
    @ApiOperation("查询用户管理的事务所列表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "firmName", value = "事务所名称", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "practiceCertificateNo", value = "事务所执业证书编号", dataType = "String", paramType = "query"), @ApiImplicitParam(name = "userId", value = "用户id", dataType = "Long")
    })
    @GetMapping("/getListOffice")
    public TableDataInfo getListOffice(String firmName, String practiceCertificateNo, Long userId) {
        List<AntiCounterfeitingRegisteredOffice> list = new ArrayList<>();
        //根据用户id去中间表查询所管理事务所id
        List<Long> longs = userService.selectUserOffice(userId);
        HashMap<String, Object> tempMap = new HashMap<>();
        tempMap.put("firmName", firmName);
        tempMap.put("practiceCertificateNo", practiceCertificateNo);
        tempMap.put("longs", longs);
        if (longs != null && !longs.isEmpty()) {
            //再去查询对应列表
            startPage();
            return getDataTable(userService.getListOffice(tempMap));
        }
        return getDataTable(list);
    }

    /**
     * 查询用户未管理事务所列表
     *
     * @param firmName              事务所名字
     * @param practiceCertificateNo 事务所执业证书编号
     * @return 结果
     * @author wph 20200914
     */
    @ApiOperation("查询无用户管理的事务所列表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "firmName", value = "事务所名称", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "practiceCertificateNo", value = "事务所执业证书编号", dataType = "String", paramType = "query")})
    @GetMapping("/getNotListOffice")
    public TableDataInfo getNotListOffice(String firmName, String practiceCertificateNo) {
        List<Long> longs = userService.selectAllUserOffice();
        HashMap<String, Object> tempMap = new HashMap<>();
        tempMap.put("firmName", firmName);
        tempMap.put("practiceCertificateNo", practiceCertificateNo);
        tempMap.put("longs", longs);
        startPage();
        List<AntiCounterfeitingRegisteredOffice> list = userService.getNotListOffice(tempMap);
        return getDataTable(list);
    }

    /**
     * 新增用户管理事务所
     *
     * @param officeId 事务所id集合
     * @param userId   用户id
     * @author wph 20200914
     */
    @Log(title = "新增用户管理事务所", businessType = BusinessType.INSERT)
    @ApiOperation("新增用户管理事务所")
    @PostMapping("/insertUserOffice")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "officeId", value = "事务所id", dataType = "List"),
            @ApiImplicitParam(name = "userId", value = "用户id", dataType = "Long")}
    )
    public AjaxResult insertUserOffice(@RequestParam("officeId") List<Long> officeId, @RequestParam("userId") Long userId) {
        return toAjax(userService.insertUserOffice(officeId, userId));
    }

    /**
     * 删除用户管理事务所
     *
     * @author wph 20200915
     */
    @Log(title = "删除用户管理事务所", businessType = BusinessType.DELETE)
    @ApiOperation("删除用户管理事务所")
    @DeleteMapping("/deleteUserOffice")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "officeId", value = "事务所id", dataType = "List", required = false),
            @ApiImplicitParam(name = "userId", value = "用户id", dataType = "Long", required = false)})
    public AjaxResult deleteUserOffice(@RequestParam("officeId") List<Long> officeId, @RequestParam("userId") Long userId) {
        return toAjax(userService.deleteUserOffice(officeId, userId));
    }

    /**
     * 修改密码接口
     *
     * @param oldPwd
     * @param newPwd
     * @return
     */
    @Log(title = "修改密码接口", businessType = BusinessType.UPDATE)
    @GetMapping("/updatePwd")
    public AjaxResult updatePwd(@RequestParam("oldPwd") String oldPwd, @RequestParam("newPwd") String newPwd) {
        String existPwd = SecurityUtils.getLoginUser().getUser().getPassword();
        if (!SecurityUtils.matchesPassword(oldPwd, existPwd)) {
            return AjaxResult.error("旧密码错误!");
        }
        return AjaxResult.success(userService.updatePwd(newPwd));
    }

    /**
     * 查询数据库有无手机号
     *
     * @return
     * @author wph 20200916
     */
    @ApiOperation("查询数据库有无手机号")
    @GetMapping("/getIsPhoneNumber")
    public AjaxResult getIsPhoneNumber() {
        return AjaxResult.success(userService.selectPhoneNumber(SecurityUtils.getLoginUser().getUser().getUserId()));
    }

    /**
     * 修改手机号
     *
     * @param phonenumber 新手机号
     * @author wph 20200916
     */
    @ApiOperation("修改手机号")
    @ApiImplicitParam(name = "phonenumber", value = "新手机号", dataType = "String", required = true)
 /*   @PreAuthorize("@ss.hasPermi('system:user:edit')")*/
    @PutMapping("/editPhoneNumber")
    public AjaxResult editPhoneNumber(@RequestBody String phonenumber) {
        return AjaxResult.success(userService.updatePhoneNumber(phonenumber));
    }

    /**
     * 修改ca的usbkey状态
     * @param antiCounterfeitingCaBlacklist
     * @return
     */
    @ApiOperation("修改ca的usbkey状态")
    @PutMapping("/updateCaUsbkeyStatus")
    public AjaxResult updateAntiCounterfeitingCaBlacklist(@Validated @RequestBody AntiCounterfeitingCaBlacklist antiCounterfeitingCaBlacklist) {
        return AjaxResult.success(userService.updateAntiCounterfeitingCaBlacklist(antiCounterfeitingCaBlacklist));
    }

    /**
     * 删除redis 的key
     * 去除密码登录等待时间
     * @return
     */
    @ApiOperation("去除密码登录等待时间")
    @PutMapping("removeKey")
    public AjaxResult removeKey(@RequestParam("username") String username){
        boolean flag = redisCache.deleteObject(Constants.LOGIN_LOCK + username);
        boolean flag2 = redisCache.deleteObject(Constants.LOGIN_PWD_ERROR_COUNT + username);
        return AjaxResult.success(flag+""+flag2);
    }
}
